/**
 * JAVACC DEMO 1.0
 * @copy right apache company All rights reserved. 
 * @Package com.apache.rpc.server.impl  
 */
package com.apache.rpc.server.impl;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import com.apache.database.constant.Validator;
import com.apache.method.SystemRunnable;
import com.apache.rpc.server.threads.ReceiveClientSocketJob;
import com.apache.rpc.server.threads.SocketConfig;
import com.apache.rpc.server.threads.ThreadScheduler;
import com.apache.rpc.util.DesUtils;
import com.apache.rpc.util.XMLMapParse;

/**
 * description:  
 * @author Hou Dayu 创建时间：2014-10-30  
 * @Copyright(c)2014:
 */
public class ProtocolSocketEncryptionServer extends SystemRunnable {

	private Socket socket = null;

	public ProtocolSocketEncryptionServer(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		String result = "";
		String key = "";
		if (null != socket) {
			key = socket.getRemoteSocketAddress().toString();
		}
		try {
			String strMsg = "";
			if (socket != null && socket.isConnected() && Thread.currentThread().isAlive()
					&& !Thread.currentThread().isInterrupted()) {
				byte[] data = new byte[102400];
				InputStream in = new BufferedInputStream(socket.getInputStream());
				in.read(data);
				strMsg = new String(data, "UTF-8");
				strMsg = strMsg.trim();
				boolean mark = true;
				Map<String, Object> headMap = new HashMap<String, Object>();
				xmlGetDataToHead(headMap, strMsg);
				String closeFlag = Validator.getDefaultStr(String.valueOf(headMap.get("SocketClose")), "false");
				mark = Boolean.valueOf(closeFlag);
				result = ClientSocketLisener.getinstance()
						.doService(strMsg, headMap.get("ParamType").toString(), false);

				byte[] data_byte_arr = result.getBytes("UTF-8");

				int data_len = data_byte_arr.length;

				byte[] data_byte_len = Int2BytesLH(data_len);

				OutputStream os = socket.getOutputStream();

				//发送实际数据长度
				os.write(data_byte_len, 0, data_byte_len.length);
				//发送实际数据内容
				os.write(data_byte_arr, 0, data_byte_arr.length);
				os.flush();
				if (!mark) {
					socket.close();
				} else {
					socket.setKeepAlive(true);
					String methodKey = String.valueOf(headMap.get("MethodCode"));
					key = key + "_" + methodKey;
					ClientSocketLisener.getinstance().setClientSocket(socket, key);
					SocketConfig config = new SocketConfig(1000, new ReceiveClientSocketJob(socket, true, key));
					ThreadScheduler.getInstance().setJobs(key, config);
					ThreadScheduler.getInstance().Start(key);
				}
			}
		} catch (Exception e) {
			try {
				socket.close();
			} catch (IOException e1) {
			}
			ClientSocketLisener.getinstance().removeSocket(key);
			e.printStackTrace();
		}
	}

	/**
	 * description:  将int转成字节数组
	 * @param n
	 * @return   
	 */
	private byte[] Int2BytesLH(int n) {
		byte[] b = new byte[4];
		b[0] = (byte) (n & 0xff);
		b[1] = (byte) (n >> 8 & 0xff);
		b[2] = (byte) (n >> 16 & 0xff);
		b[3] = (byte) (n >> 24 & 0xff);
		return b;
	}

	private void xmlGetDataToHead(Map<String, Object> headMap, String strMsg) {
		String params = DesUtils.getInstance().decrypt(strMsg);
		if (params.startsWith("[{")) {//json方式传入
			params = XMLMapParse.instance().jsonToXMl(params);
		}
		if (params.startsWith("<?")) {//xml方式传入
			XMLMapParse.instance().xmlGetDataToHead(params, headMap);
		}
	}

}
